home *** CD-ROM | disk | FTP | other *** search
- From: Tom Truscott <decvax!mcnc!rti-sel!trt>
- Subject: wm - a window manager (part 1 of 4)
- Newsgroups: mod.sources
- Approved: john@genrad.UUCP
-
- Mod.sources: Volume 2, Issue 31
- Submitted by: Tom Truscott <decvax!mcnc!rti-sel!trt>
-
-
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create the files:
- # README
- # wm.1
- # USINGWM
- # Paper.jacob
- # This archive created: Fri Aug 2 13:13:13 1985
- export PATH; PATH=/bin:$PATH
- echo shar: extracting "'README'" '(1606 characters)'
- if test -f 'README'
- then
- echo shar: will not over-write existing file "'README'"
- else
- sed 's/^X//' << \SHAR_EOF > 'README'
- A Revised Edition of the `wm' window manager
- Matt Lennon (919) 541-6919
- Tom Truscott (919) 541-7005
- Research Triangle Institute, NC
- P.O. Box 12194
- RTP, NC 27709
-
-
- To install WM:
-
- 1) Install the provided version of the Curses library. This library
- has bug fixes *necessary* to the proper operation of WM.
- If you don't actually install libcurses.a in /usr/lib, you
- must indicate this in the WM Makefile (the LIBCURSES macro),
- and you must copy the provided curses.h to this directory
- so that it will be included during compilation.
-
- 2) Set the value of BIN in the WM makefile to the
- directory where the WM program should reside.
-
- 3) Type 'make install'.
-
- 4) Install the WM manual page, wm.1, in the appropriate place.
-
-
- Note 1: This version of WM is horribly 4.2bsd-dependent, using pseudo-ttys,
- the 'select()' system call, 4.2-specific ioctl's, etc.
- Conceivably, it could be made to run under 4.1bsd with some
- minor mods, but porting to other versions of UNIX would
- probably entail a major rewrite.
-
- Note 2: The paper 'USINGWM' is a brief essay on how we use WM
- here at RTI, and should prove helpful in getting used to
- the WM style of doing things. It also describes some
- problems/glitches with WM that you should be aware of.
-
- Note 3: Included in this distribution is a paper (Paper.jacob)
- by the original WM author that describe WM's
- development and structure. While the description of
- the 4.2bsd version of WM pertains to an earlier version,
- the basics are still the same, and this paper is good reading.
- SHAR_EOF
- if test 1606 -ne "`wc -c < 'README'`"
- then
- echo shar: error transmitting "'README'" '(should have been 1606 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'wm.1'" '(5635 characters)'
- if test -f 'wm.1'
- then
- echo shar: will not over-write existing file "'wm.1'"
- else
- sed 's/^X//' << \SHAR_EOF > 'wm.1'
- X.TH WM local wm
- X.SH NAME
- wm \- window manager
- X.SH SYNOPSIS
- X.B wm
- [ \fB\-n\fP ] [ \fB\-f\fP rfile ]
- X.SH DESCRIPTION
- X.I Wm
- manages a collection of windows on a display terminal.
- X.PP
- It determines what type of terminal you are using from
- the environment parameter $TERM
- (see
- X.IR environ (5))
- and then uses
- X.IR curses (3)
- to adapt to it.
- X.PP
- Each window has its own UNIX shell
- (as specified by the environment parameter $SHELL;
- the default is
- X.IR sh (1)),
- running in parallel with those in the other windows.
- The idea behind this scheme is that you can use each window
- for a series of commands dealing with a single topic.
- Then, you can change back and forth between the windows without
- losing your place in any of them.
- X.PP
- At any time, you can give commands to change the window you are typing in,
- to move a window or change its size,
- or to create or kill a window.
- Windows can overlap or completely obscure one another.
- Obscured windows can subsequently be "lifted" up
- and placed on top of the other windows.
- When a window is partially or completely obscured,
- subsequent output to that window will be held until the window
- becomes completely visible again, effectively suspending the job
- running in the obscured window.
- X.PP
- When the program is started,
- it will attempt to restore the sizes and positions of the windows
- in use when you last ran
- X.IR wm
- (unless you use
- X.B \-n
- option).
- If you give the
- X.B \-f
- X.I rfile
- option,
- X.I wm
- tries to restore windows from the file
- X.I rfile.
- Otherwise, it first tries the file
- X.I .wmrc
- in the current directory,
- then, if necessary,
- X.I .wmrc
- in your home directory.
- XFailing all this,
- X.I wm
- will give you a window the size of your screen.
- Now, you can type UNIX commands in the new window.
- X.PP
- X.I Wm
- commands can be issued at any time.
- Every
- X.I wm
- command consists of a prefix character \fI<wm-esc>\fP followed by one
- more character, possibly followed by some arguments.
- Any other characters typed on the terminal are treated as input
- to the program in the current window.
- To enter \fI<wm-esc>\fP itself as input to a program, type it twice.
- The \fI<wm-esc>\fP is initially set to ASCII ESC, but there is
- a command for changing it.
- X.PP
- The available
- X.I wm
- commands are \fI<wm-esc>\fP followed by:
- X.IP \fBn\fP
- Create a new window.
- To do this, move the cursor to the position you want the
- lower left corner of your window
- to occupy,
- using the keys
- X.B k
- (up),
- X.B j
- (down),
- X.B h
- (left), and
- X.B l
- (right)
- and also
- X.BR K ,
- X.BR J ,
- X.BR H ,
- and
- X.B L
- (for large increments in the respective directions).
- Then type an
- X.BR x .
- Then move the cursor (using the same commands) to the upper
- right corner, and type another
- X.BR x .
- X.IP \fBi\fP
- Identify each window by outlining it with its window number
- (each window has a one digit name, e.g.
- #\fB1\fP, #\fB2\fP, #\fB3\fP,
- used in referring to that window).
- X.IP \fIdigit\fP
- Change the current window.
- The named window is placed on "top" of the screen
- (that is, in front of any other windows that had been obscuring it).
- Input from the keyboard will now be sent to this window.
- (Delayed responses to commands entered in other windows will,
- of course, continue to be routed to their correct windows.)
- X.IP \fBl\fP
- Change to the last-used window.
- Change back to the window that had most recently been the current window.
- X.IP \fBm\fP
- Move and/or change the size of the current window.
- X.I Wm
- asks for the lower left and upper right corners of desired
- new position of the window (same convention as for new windows).
- It is not advisable to move a window except when
- the program running in it is at the shell prompt level.
- In particular, screen-oriented programs such as
- X.I vi
- can get very confused if their window size is changed while they are running.
- X.IP \fBt\fP
- Reset the environment variables $TERM and $TERMCAP for the current window.
- This may be necessary if these variables get unset or scrambled,
- for instance during a remote login.
- This command should only be invoked when
- the program running in it is at the shell prompt level because
- it operates by sending commands to the shell as if
- they were typed in from the keyboard.
- X.IP \fBd\fP
- Dump current window contents. An image of the current window is
- written to the file
- X.I wmdump
- in the current directory.
- X.IP \fBk\fP
- Kill the named window.
- XSends the signal SIGHUP (hangup) to the processes associated with the window,
- then erases the window.
- (The
- X.I name
- of this window may later be re-used in creating a new window.)
- X.IP \fBp\fP
- Change the prefix character.
- X.IP \fBr\fP
- Redraw the screen.
- Clears the entire screen and redraws what should be there.
- Helpful after garbage (like a broadcast message) has arrived.
- X.IP \fBq\fP
- Quit.
- End the current
- X.I wm
- session.
- XFirst terminates the processes associated with each
- X.I wm,
- window by sending them the signal SIGHUP (hangup).
- Then, if you have changed the window configuration during the session
- (and didn't specify the 'no restore' (\fB\-n\fP) option),
- asks you if you want to save the current window configuration
- for the next session.
- Then exits.
- X.IP \fBz\fP
- XSuspend
- X.I wm
- by using the Berkeley job control system,
- or perhaps by spawning a non-window subshell.
- X.IP "\fBh\fP or \fB?\fP"
- Help.
- Displays a summary of
- X.I wm
- commands.
- X.SH FILES
- X.IP \fI.wmrc\fP
- X.IP \fI$HOME/.wmrc\fP
- used to save the arrangement of your windows from one session to the next.
- X.SH BUGS
- It'll never beat a BLIT.
- X.SH "SEE ALSO"
- R.J.K. Jacob,
- "User-Level Window Managers for UNIX,"
- X.I "Proc. UniForum International Conference on UNIX,"
- pp. 123-133 (1984).
- X.SH AUTHOR
- Robert J.K. Jacob
- X.br
- Naval Research Laboratory
- X.sp
- Revised by Matt Lennon and Tom Truscott
- X.br
- Research Triangle Institute
- SHAR_EOF
- if test 5635 -ne "`wc -c < 'wm.1'`"
- then
- echo shar: error transmitting "'wm.1'" '(should have been 5635 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'USINGWM'" '(17319 characters)'
- if test -f 'USINGWM'
- then
- echo shar: will not over-write existing file "'USINGWM'"
- else
- sed 's/^X//' << \SHAR_EOF > 'USINGWM'
- X.TL
- How I use WM
- X.AU
- Tom Truscott
- X.AI
- Research Triangle Institute
- P.O. Box 12194
- RTP, NC 27709
- (919) 541-7005
- X.SH
- XStarting up wm
- X.PP
- The last line in my .profile is
- X.DS
- X.ft PO
- exec wm
- X.ft P
- X.DE
- which puts me into the window manager,
- so I am always in it.
- When I need a real terminal
- (e.g. to run `talk')
- I can type \fI<wm-esc>\fPz.
- XSince I go right into wm
- it is important
- that TERM be set correctly.
- Earlier in my .profile I have
- X.DS
- X.ft PO
- export TERM
- case "$TERM" in
- sw|su) TERM=`whatterm`;;
- esac
- X.ft P
- X.DE
- XSo that if the TERM variable is su or sw (dataSWitch)
- John Menges' whatterm program is invoked to figure things out.
- (Whatterm depends on the
- response characteristics of a dozen or so terminals.
- A more general version, using a `responsecap' database,
- is planned.)
- Whatterm is doomed to fail on an ADM terminal
- (unless it has the HERE-IS option)
- and also fails
- if the user is already in wm and and logging in to another computer,
- because `wm' itself does not respond to any escape sequences.
- It probably should, so whatterm will work!
- Actually, nested invocations of wm, while amusing,
- are probably unnecessarily confusing.
- X.SH
- Choosing window layout
- X.PP
- That is largely a matter of individual taste.
- My ``#1'' window is full-screen (except for the bottom line),
- my #2 window is the top half of the screen and my #3
- window is the bottom half (with an unused line between them),
- and my #4 window is just like #1.
- I am normally (99%) in the #1 window and am generally
- unaware of the existence of wm.
- But when I want
- to escape from the current window I can change to window #4
- to get a fresh screen (one wm nuisance is
- that it puts me back in my home directory on my home machine).
- Or if I want split screens, say for debugging or file comparison,
- I can change to window #2 and then alternate between #2 and #3.
- I think of having three window layers, the #1 layer,
- the #2/#3 layer, and the #4 layer.
- (In reality, wm maintains a window display order,
- and changing to a window puts that window on `top',
- so there is not really a #2/#3 layer.)
- On a 66 line display I bet things would be much nicer.
- XSome people have a window which covers all but the top line,
- so they can put a clock or periodic `uptime' in the top line.
- (Note: two windows \fImust\fP have an unused line between them
- or else they cannot be used for simultaneous displays.)
- Also, some people change the wm prefix character to `^W' or `^P'
- so that `vi' is easier to use.
- X.PP
- The undocumented experimental \fI<wm-esc>\fPf (`fit') command is also handy.
- XFor example, suppose I am in my #1 window and type ``make''.
- It might take a while, so I would like to switch to another window
- and read news.
- But I would also like to see the progress of the make.
- XSo I switch to a half-screen window and type `\fI<wm-esc>\fPf 1',
- which relocates the #1 window so that it is no longer obscured.
- Now I can read news and keep up with the ``make'' at the same time.
- This can really jumble up the windows,
- but in this case I can change back to #1
- and do a `\fI<wm-esc>\fPf 1' to make it full-screen again.
- X.SH
- Window ``Performance'' Considerations
- X.PP
- There are some important performance details to consider.
- XFirst, your terminal needs insert-line/delete-line
- or scrolling region support for wm to work well
- on anything but full-screen windows.
- In particular, my #2/#3 windows are sloowww without such support.
- The scrolling region is best because with insert/delete-line
- scrolling in the #2 window causes the #3 window to jitter up and down.
- By the way, the scrolling region capability is often omitted in
- many termcap entries, so you might need to put it in.
- Here is the relevant vt100 stuff, which is probably the
- only scrolling region support you are likely to find:
- X.DS
- X.ft PO
- X.\" note: the '\e' below is troff's way of saying '\'
- :sc=\eE7:rc=\eE8:cs=\eE[%i%d;%dr:sr=5\eEM:
- X.ft P
- X.DE
- XFor now, all of ``cs'', ``sc'', ``rc'', and ``sr'' must be specified
- or wm will not use scrolling regions.
- X.PP
- By all means you should make windows be the full width of the screen.
- Without that wm scrolls by redrawing the whole window.
- The painful slowness is tolerable for smaller windows,
- and also for faster terminal speeds.
- My office terminal is at 4800 baud, and wm is okay at that speed,
- but even 19200 is probably too slow for a window that is full-screen
- except for the right-most column.
- X.SH
- WM Enhancements
- X.PP
- The ``Hacking WM'' document mentions several possible enhancements.
- XSuggestions for other improvements to wm are welcome.
- Code for any new improvements are even more welcome!
- X.bp
- X.TL
- Hacking WM
- (Obscure Details for the Hard-Core User)
- X.AU
- Tom Truscott
- X.AI
- Research Triangle Institute
- P.O. Box 12194
- RTP, NC 27709
- (919) 541-7005
- X.SH
- In Praise of Matt Lennon
- X.PP
- Matt Lennon took an interest in Robert Jacob's Usenet wm distribution,
- got it running here, and talked others into trying it out.
- XFrankly, the original version was too slow to be usable,
- although it was indeed interesting.
- (Perhaps most interesting of all was that Jacob had a version
- of wm running under UNIX V6!)
- Matt reorganized the program internally and put in the first
- of a series of scrolling hacks (in WMinsertln and WMdeleteln).
- The resulting program shares with the original wm a simplicity of design
- that is important in any program, but particularly in a window manager.
- I think of the revised wm as the ``A'' version.
- I am afraid a ``B'' version will be along all too soon.
- X.SH
- Problems with Running Programs under WM
- X.PP
- There are three common problems when running programs under wm.
- One problem is that some programs assume
- the screen is at least some minimum size, such as 24 lines and 80 columns.
- Typical programs betray themselves by scribbling text
- intended for ``line 24'' at random places on the screen,
- or by dumping core after the ``newwin'' curses routine refuses
- to create a window that encompasses that line.
- XFixing such programs can be a chore,
- but often one can just substitute `COLS' for 80, `LINES-1' for 23,
- and so on.
- Rogomatic demands 24 lines so I hacked it to overlay all lines >= LINES
- onto line LINES-1, which is messy but tolerable.
- XFor programs beyond hope, type \fI<wm-esc>\fPz and run the program
- on the real terminal.
- X.PP
- A second problem is with programs that assume a specific terminal type,
- such as "vt100".
- Wm currently understands only the pseudo-terminal
- type "wmvirt", so such programs cannot be run under wm.
- It would be nice if wm could emulate an arbitrary
- terminal type.
- Then one could run wm on an ADM terminal
- with one window emulating a vt100 and another emulating a Tektronix 4014.
- Of course, wm would need to support viewports into windows.
- Viewports are trivial compared to emulating 4014 graphics, however.
- X.PP
- A third problem is that some programs use getlogin
- to determine the user's login name,
- but under wm getlogin fails since no one is logged in
- on the window's control terminal (pseudo-tty).
- The easiest fix is to replace calls to getlogin
- with calls to safegetlogin:
- X.DS
- X.ft PO
- /*
- * Returns a user name such that uid(user name) == getuid().
- * If feasible, the session login name is used,
- * but if the real uid has been changed (e.g. via 'su')
- * or if certain file descriptors have been munged
- * then a user name corresponding to the real uid is returned instead.
- * Returns NULL if everything fails.
- * Beware! Clobbers static data from earlier calls to getpw*.
- */
-
- #include <pwd.h>
-
- char *
- safegetlogin()
- {
- register char *p;
- register int uid;
- register struct passwd *pwd;
- static char namebuf[50];
- extern char *getlogin();
-
- uid = getuid();
- p = getlogin();
- /* cannot trust getlogin, so here is a security check */
- if (!p || !(pwd = getpwnam(p)) || uid != pwd->pw_uid)
- p = 0;
- /* if getlogin failed, try the real uid */
- if (!p && (pwd = getpwuid(uid)))
- p = pwd->pw_name;
- if (p) {
- strncpy(namebuf, p, sizeof(namebuf)-1);
- p = namebuf;
- }
- return(p);
- }
- X.ft P
- X.DE
- This fixes the `galaxy' and `robots' programs, for example.
- We keep this routine in /usr/local/liblocal.a and link programs
- that call it with `-llocal'.
- Alas, one case that this misses is the command ``who am i''.
- The trade secret status of ``who'' precludes a clearer explanation.
- X.SH
- XSupport for Fast Scrolling of any Rectangular Window
- X.PP
- A (very) few terminals support general ``scrolling rectangles.''
- These are wonderful for wm because then
- non-full-width windows scroll quickly.
- Terminfo already has the ``set_window'' string capability,
- described in `tparm' format,
- to set up a scrolling rectangle.
- There is no such capability in termcap so a new ``sw''
- capability was invented, using the same format as terminfo.
- XFor example, for the HDS Concept 108 we have:
- X.DS
- X.ft PO
- X.\" note: the '\e' below is troff's way of saying '\'
- :sw=\eEv%p1%' '%+%c%p3%' '%+%c%p2%p1%-%'!'%+%c%p4%p3%-%'!'%+%c:\e
- X.ft P
- X.DE
- XFor the HDS 200 we have (sorry, this is untested):
- X.DS
- X.ft PO
- X.\" note: the '\e' below is troff's way of saying '\'
- :sw=\eE[%p1%{1}%+%d;%p2%{1}%+%d;%p3%{1}%+%d;%p4%{1}%+%dr:\e
- X.ft P
- X.DE
- You also need ``sr'' (scroll_reverse) for wm to use set_window.
- Wm assumes that the set_window command moves the cursor
- to the rectangle's home position (upper left),
- that cursor motion commands work in the rectangle,
- and that the motions are relative to the origin of the rectangle.
- If your terminal works differently, and it probably will,
- you might have to hack wm.
- Look for "SET_WINDOW" which, if defined, causes
- code to be generated to support scroll rectangles.
- X.SH
- LIBCURSES
- X.PP
- Wm depends heavily on the underlying screen management software (libcurses)
- for correctness and efficiency.
- A number of changes were found to be needed in libcurses
- to provide correctness.
- The major efficiency problem has been that of providing fast scrolling.
- Libcurses itself does not support insert/delete line or
- scrolling regions to provide fast scrolling.
- We decided not to put such support into libcurses,
- because that was considered too far-reaching,
- so insert/delete line and scrolling regions are handled
- within special code in wm itself,
- and the libcurses windows are accordingly fixed up.
- Wm could support scrolling regions more efficiently
- (by not switching back and forth between full screen
- and window-sized regions on every newline).
- It could also handle certain non-full-width windows better.
- XFor example to scroll a window that covers all but the rightmost column
- it could scroll all lines involved and then redraw the rightmost column.
- Perhaps the termlib or other packages do that sort of thing.
- Also, for non-full-width windows wm could perhaps scroll two
- or more lines at a time, or possibly even wrap around
- to the top line rather than scroll.
- X.SH
- WM and TERMINFO
- X.PP
- Wm can be compiled with
- Pavel Curtis' public domain ``terminfo'' library
- in addition to the usual one (``Curses Classic'').
- During compilation the TERMINFO preprocessor variable is defined
- if compilation with terminfo curses is detected,
- so that appropriate code is generated.
- The terminfo conventions are nicer than the classic version
- so wm uses the terminfo functions and variable names,
- and Curses Classic is supported by redefinitions and emulation routines.
- X.PP
- However, wm really should only be compiled with Curses Classic.
- The terminfo version is slower, bigger, buggier, and does not
- support arrow keys.
- Terminfo also has more fundamental problems.
- It does not provide support for the TERMCAP environment variable,
- and there is no easy way to construct a terminfo binary file
- analogous to the 'wmvirt' TERMCAP string.
- As a result wm cannot support any terminfo-compiled applications programs.
- When (if) this becomes a problem there will be additional incentive
- for wm to be able to emulate an arbitrary terminal
- (also see ``problems with running programs under wm'', above).
- Then, in conjunction with the 4.3 kernel support for window sizes,
- wm can dispense with the TERMCAP variable and emulate whatever
- terminal is desired, thus supporting both termcap and terminfo.
- (\fI<wm-esc>\fPt will still be needed for tip and cu.)
- X.SH
- WM response sluggishness
- X.PP
- An unfortunate current side-effect of wm is that certain
- normally responsive terminal operations are now sluggish.
- XFor example, if you cat a file and press <Interrupt>
- several lines will be printed before the interrupt
- takes effect.
- Other similar special characters are also handled slowly.
- The reason is that wm runs in raw mode, so such characters
- are not ``instantly'' handled in the kernel.
- Instead they are passed to the currently selected
- pseudo-tty, which then interrupts or stops or whatever.
- But any characters currently queued by wm for the user's terminal
- are still printed!
- (The script program has the same behavior,
- but it is tolerable for the normal uses of that command.)
- There does not seem to be a good way around this problem.
- Wm's current approach is to
- X.IP a)
- Only read a few (currently 64) characters from each pseudo-tty
- at a time, to avoid large queues from wm to the real tty.
- X.IP b)
- Have wm check the size of the output queue using the undocumented
- TIOCOUTQ ioctl, and delay reading from the pseudo-ttys
- if the output queue is large.
- X.IP c)
- Have wm reduce the read and queue sizes for a while after the user
- types Control-S.
- X.LP
- The first two hacks keep the response to <Interrupt> at a tolerable level.
- They also keep the tty high water mark from
- being reached, which would put wm to sleep,
- which would make response very sluggish indeed.
- The last hack gives somewhat better response to Control-S.
- X.PP
- This approach to wm sluggishness is quite new,
- so more tuning and better approaches to the problem are possibilities.
- Also, the parameters have been tuned for a Gould 9050,
- which is quite a fast machine, and the resulting
- extra cpu involved might be intolerable on a VAX.
- An easy `fix' is to comment out the TIOCOUTQ code in wm.c
- (you can probably just #undef TIOCOUTQ at the top).
- You might want to remove the Control-S hack as well.
- X.SH
- The `.wmrc' File
- X.PP
- The first line of .wmrc is the prefix character.
- The remaining lines describe the configured windows from bottom
- to top.
- (The last line describes the window in which the user starts.)
- Each line consists of the window name, the number of rows and columns,
- and the starting row and column (zero indexed).
- If the number of rows (columns) is given as zero then that dimension
- ``flexes'' to the height (width) of the screen,
- which supposedly is useful when switching among terminals
- of different sizes.
- X.PP
- XSeveral users have asked for the ability to specify an alternate ``shell''
- in a window.
- That could be done by extending the .wmrc lines to include
- a command to be executed in lieu of the shell.
- Other users have requested the ability to set the shell prompts
- in a window dependent way, among other things.
- I do not know how that might be done.
- X.SH
- The ``SNEAKYTERMCAP'' Method
- X.PP
- Ordinarily, when a window changes size, wm blasts the window
- with a shell command that sets TERM and TERMCAP
- to indicate the new window's size.
- (This is the same shell command generated by \fI<wm-esc>\fPt.)
- This not only produces clutter, it can also confuse non-shell
- programs running in that window.
- If your version of wm was compiled with SNEAKYTERMCAP defined,
- however, a different method is used.
- The TERMCAP variable is set to a filename such as /tmp/WM.33445.1
- and the file contains the termcap capability string.
- Then, when a window changes size the /tmp file is simply rewritten.
- But there is a security problem with this method
- (or with any command that uses /tmp)
- and /tmp gets cluttered up with lots of ``WM'' files.
- It would be better if the files were kept in a subdirectory
- of each user's home directory, and if wm itself cleaned
- up dead temporary files (e.g. due to a system crash).
- X.SH
- Browsing About in WM Windows
- X.PP
- XSome terminals have extra memory so one can look back
- at text that scrolls off the screen.
- It would be nice if wm provided that too.
- One hundred lines of scrolled typescript should be adequate.
- A plausible approach would be to type \fI<wm-esc>\fPv
- (for `view') to put the window in browse mode.
- Then input to that window is interpreted as requests
- to move back and forth in the typescript,
- like the `vi' scrolling commands.
- Any output to the real window is held pending exit from browse mode,
- which might be by typing ``:q'', at which time the window
- is reset to its state on entry to browse mode.
- Of course, while a window is in browse mode one can still
- switch between windows, move, create, and kill windows, and so on.
- X.PP
- All this can be implemented cleanly with about 100 lines of code
- scattered here and there (it has been written),
- but what about text searching and the ability to write parts
- of the typescript into UNIX files?
- What about all the other nifty `vi' commands?
- Why not just run `vi' (or your favorite viewing program)
- in the browse window!?
- Well, here is why not.
- Vi has to position itself at the end of the typescript
- in order to provide a ``seamless interface'' to wm.
- Okay, that's easy.
- We need an ``ignore first clear'' kludge so that when
- vi initially redraws the screen
- the window is not really redrawn.
- Uh, well, wm already has kludges.
- We need to suppress the vi status line (``seamless interface'' remember),
- say by displaying it instead in wm's status area.
- Er, uhm. Yuck!
- It could be done, but it sure would be ugly.
- Alas, wm does not yet support browse mode.
- SHAR_EOF
- if test 17319 -ne "`wc -c < 'USINGWM'`"
- then
- echo shar: error transmitting "'USINGWM'" '(should have been 17319 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'Paper.jacob'" '(22963 characters)'
- if test -f 'Paper.jacob'
- then
- echo shar: will not over-write existing file "'Paper.jacob'"
- else
- sed 's/^X//' << \SHAR_EOF > 'Paper.jacob'
- X.rm CH
- X.ds CF "\(hy \\n(PN \(hy
- X.\"
- X.ds >. .
- X.rm <.
- X.ds >, ,
- X.rm <,
- X.ds [. " [
- X.ds .] ]
- X.\"
- X.TL
- User-Level Window Managers for UNIX
- X.AU
- Robert J.K. Jacob
- X.AI
- Naval Research Laboratory
- Washington, D.C. 20375
- X.AB
- X.I Wm
- manages a collection of windows on a display terminal.
- Each window has its own shell or other interactive program,
- running in parallel with those in the other windows.
- This permits a user to conduct several interactions with the system in
- parallel, each in its own window.
- The user can move from one window to another, re-position a window, or
- create or delete a window at any time
- without losing his or her place in any of the windows.
- Windows can overlap or completely obscure one another;
- obscured windows can be "lifted" up
- and placed on top of the other windows.
- X.PP
- This paper describes how such a window manager for UNIX\(dg
- X.FS
- X.PP
- \(dgUNIX is a trademark of Bell Laboratories.
- X.FE
- is implemented as a set of user processes,
- without modifications to the UNIX kernel.
- It shows how the simple, but well-chosen
- facilities provided by the original
- (Version 6) UNIX kernel are sufficient to support
- X.I wm .
- In addition, subsequent versions of
- X.I wm
- exploit features of the kernel introduced into newer versions of
- UNIX to provide faster and more sophisticated window operations,
- still implemented entirely at the user level.
- X.AE
- X.SH
- Introduction
- X.PP
- This paper describes the design of a display window manager for
- UNIX implemented entirely as a set of user processes, without modifications to
- the UNIX kernel.
- It shows how the simple facilities provided by the original
- (Version 6) UNIX kernel are sufficient to support such a window
- manager.
- In addition, more recent versions of the window manager exploit
- features of the kernel introduced into newer versions of UNIX to
- provide faster and more sophisticated operations in windows,
- still implemented entirely outside the kernel.
- X.PP
- This window manager,
- X.I wm ,
- provides a UNIX
- user the ability to conduct several interactions in parallel, each in
- a different window on a text display terminal.
- The windows may be created, moved, and temporarily or permanently erased
- at any time.
- They may also overlap or completely obscure one another, and such hidden or
- partially hidden windows may be "lifted" and placed on top of the
- other windows as desired.
- XFigure 1 shows a snapshot of a
- X.I wm
- session in progress.
- X.SH
- User Interface
- X.PP
- The notion of organizing computer data spatially was propounded
- and exploited by Nicholas Negroponte in the Spatial Data Management System\*(<.\*([.2,\|3\*(.]\*(>.
- In
- X.I wm ,
- however, spatial cues are used only to specify a context for a dialogue.
- Once a window is selected, further interactions within that window
- make use of the
- power and abstraction of more conventional user interface techniques.
- Teitelman\*([.8\*(.]
- made good use of display screen windows for
- a collection of parallel interactions with an INTERLISP system.
- More recently, several personal computers and workstations have adopted this
- window-oriented style of dialogue as their principal mode of interaction.
- Other systems similar to the present one have also been provided
- under UNIX\*(<.\*([.4,\|7,\|9\*(.]\*(>.
- X.PP
- Traditional user interfaces for computers
- that handle parallel processes
- place all inputs and outputs in one chronological
- stream, identifying the process associated with each, but interleaving
- the data.
- The Berkeley job control facilities for UNIX
- provide a first attempt at improving this situation\*(<.\*([.5\*(.]\*(>.
- X.PP
- By contrast, a window-based user interface
- enables a user to manage a collection of dialogues by
- associating a spatial location with each dialogue, in much the same
- way one organizes a desk.
- On a desk, all input papers on all topics
- are not (one hopes) placed on a single
- pile in chronological order, but rather they are divided into piles by topic.
- When input for a particular topic is received, the corresponding pile
- is located, lifted, and placed on top of other papers, and the necessary
- work is done on that pile.
- Each topic may thus be associated with
- and remembered in terms of a location on the desk.
- Recent empirical evidence showed that such a window-oriented
- user interface induced better user performance than a more
- traditional scrolled message interface in a particular
- situation involving several parallel interactions\*(<.\*([.6\*(.]\*(>.
- X.PP
- X.I Wm
- conducts several concurrent dialogues with a UNIX user.
- Each takes the form of a UNIX shell, to which
- UNIX commands can be given and from which other interactive
- programs can be initiated.
- Each dialogue is conducted in a separate area of the screen or
- X.I window
- designated by the user.
- At any moment, one of the windows is considered the current input window,
- and all keyboard inputs (except for
- X.I wm
- commands themselves) are sent to the shell
- or program associated with that window.
- At any time (including in the middle of typing a command in a window),
- the designation of the current window may be changed
- and a different dialogue begun or resumed.
- Outputs resulting from these dialogues will appear in their appropriate
- windows as they are generated, regardless of which window is the
- current input window.
- Output destined for a portion of a window that is obscured by another
- window will appear whenever that portion of the window is uncovered.
- Windows can be "piled" on one another in any sequence.
- X.PP
- X.I Wm
- was originally designed for use in an intelligent terminal
- that could communicate with several computers simultaneously.
- Each dialogue with a different computer was associated with a window.
- The method is equally applicable to a collection of dialogues,
- all with the same computer but on different topics.
- XStill, any or all of the present windows can run programs to conduct
- interactive dialogues with other computers
- (such as
- X.I telnet ).
- X.SH
- Design for "Vanilla" UNIX
- X.PP
- To implement a system of this sort,
- it is necessary for one user process to be able to
- manage a collection of other user processes and to mediate all of
- their inputs and outputs.
- XFor the inputs, it must act as a switch, directing input from the keyboard to
- different programs in response to user commands.
- XFor the program outputs,
- it must place the output of each program in its correct
- position on the screen.
- X.PP
- If adequate primitives for creating and manipulating processes
- and for catching their inputs and outputs are provided by the
- operating system, a window manager can be built entirely as a
- user program.
- The original design of UNIX, with its
- X.I pipe
- and
- X.I fork
- mechanisms provides a user the right primitives to design such a
- system in an elegant fashion without kernel modifications.
- X.PP
- X.I Wm
- initiates and manages its own collection of UNIX processes, including
- those run in response to entered commands.
- Any conventional UNIX program can be used from
- X.I wm ,
- provided it does not make significant
- assumptions about the nature of its input
- and output devices\-that is, it should treat input and output from a
- pipe as equivalent to input and output from a terminal or other source.
- X.PP
- X.I Wm
- runs as
- X.I 2n+2
- parallel UNIX processes of four different types
- (where
- X.I n
- is the number of windows in use).
- The division into processes is dictated by the fact that the original UNIX
- X.I read
- call on an empty pipe or input device causes a process to
- block until input becomes available.
- Hence there is a separate process for each pipe or device that must be
- read asynchronously.
- Each such process contains a loop that reads from its
- particular pipe or device,
- processes the input, and then waits for more.
- XFigure 2 shows the processes and pipes that comprise
- X.I wm .
- X.PP
- The
- X.B main
- process reads from and waits for input from the keyboard.
- Input consisting of text is sent to the shell process
- associated with the current window and also to the
- X.B scrn
- process, described below, for echoing.
- Input consisting of
- X.I wm
- commands is interpreted by
- X.B main ,
- translated into one or more primitive commands plus arguments, and sent to
- X.B scrn
- for execution.
- XSimple changes in the input command language are thus localized in
- X.B main .
- To change the name, input syntax, or prompt for a command, only the code in
- X.B main
- need be modified.
- XSince input commands are reduced to a somewhat more general set of
- primitive commands, some simple new commands may be implemented entirely in
- X.B main
- as aliases for specific uses or combinations
- of the existing primitive commands.
- X.PP
- The
- X.B scrn
- process handles all outputs to the screen.
- All processes that want to affect the screen must thus place requests
- to do so on a common pipe.
- X.B Scrn
- reads these instructions from the pipe and makes appropriate modifications to
- the screen.
- X.I Wm
- commands that affect the screen layout, such as moving a window, are placed
- on this pipe by
- X.B main
- and handled by
- X.B scrn .
- Output text characters from the individual shell processes
- that belong in a window
- are also placed on this pipe along
- with a window identifier and a bit
- indicating whether the character should be displayed immediately or
- just remembered for the next time the display is refreshed.
- X.B Scrn
- then compares the desired configuration of the screen to a buffer
- containing the actual configuration
- and transmits the necessary updates.\(dg\
- X.FS
- X.PP
- \(dgThe update algorithm
- is less sophisticated than the optimization performed in the
- X.I curses
- package\*(<,\*([.1\*(.]\*(>,
- but
- X.I curses
- was not available in Version 6 UNIX.
- This update algorithm
- is also somewhat easier to adapt to unusual terminals, as seen below.
- X.FE
- X.PP
- There is a
- X.B shell
- process associated with each window.
- This is simply the standard UNIX
- X.I sh
- (or any other designated program).
- These
- X.B shell
- processes have no direct access to the terminal, but run as captives of
- X.I wm ,
- connected by pipes, so that their inputs and outputs can be mediated.
- The input to each of these processes is a pipe from
- X.B main ,
- since
- X.B main
- knows which window is the current input window and can place the typed
- input text on the pipe to the corresponding
- X.B shell
- process.
- All outputs of the
- X.B shell
- processes must be sent to
- X.B scrn
- to be displayed, but they must first be tagged with the name of the
- window in which they belong.
- X.PP
- To do this, each window has a
- X.B shmon
- process that monitors the output of the corresponding
- X.B shell
- process.
- The output of each
- X.B shell
- process is a pipe to a corresponding
- X.B shmon
- process.
- Each time output appears on that pipe,
- X.B shmon
- reads it, packages it with a header identifying its window,
- and then places it on the common request pipe to
- X.B scrn .
- X.PP
- X.I Wm
- comprises about 1000 lines of C code\-about 500 each for the
- X.B main
- and
- X.B scrn
- processes and less than 50 for the
- X.B shmon
- process.
- X.SH
- Remarks and Problems with "Vanilla" UNIX
- X.PP
- Each window in
- X.I wm
- emulates an individual glass teletype.
- Inputs appear in the bottom and scroll off the top of a window.
- XSince the standard input and output for all programs run by
- X.I wm
- are really pipes,
- all programs run under
- X.I wm
- should treat their inputs and outputs
- simply as streams of characters, without distinctions between
- terminals and pipes.
- The fact that UNIX and most of its original programs permit a pipe to be
- substituted for a terminal input or output stream is an elegant
- aspect of UNIX that is crucial to
- X.I wm .
- This obtains for most UNIX programs;
- they perform individual "building-block" functions and are thus intended
- to be equally usable individually from the terminal
- or as filters connected to other programs to perform more complex tasks.
- Programs that try to determine whether they
- have access to a real terminal may behave differently or even refuse to run with
- X.I wm .
- XFor example,
- X.I stty
- is meaningless when applied to a pipe rather than a terminal,
- X.I vi
- will refuse to run from a pipe,
- and
- X.I csh
- will not allow job control if it cannot access the terminal.
- (However, note that
- X.I wm
- is really an alternate approach to controlling concurrent jobs.)\
- X.PP
- A very rudimentary facility for supporting a
- whole-screen-oriented program is provided.
- It creates a special temporary window,
- creates a
- X.I termcap
- description of a "terminal" that occupies only the corresponding
- area of the actual
- screen, and then provides that description and direct access to the terminal
- to the screen-oriented program until the latter exits.
- X.PP
- XSince
- X.I wm
- operates with the terminal in raw mode,
- it must provide for itself the input line editing functions normally
- provided by the teletype driver.
- X.PP
- Because of the architecture of
- X.I wm ,
- there are no pipes that
- connect one window to another, hence there is no explicit facility for
- communication between windows.
- It can be achieved, however, through the file system.
- A program in one window
- can append to a file while one in another window continuously tries to read
- from the end of that file.
- X.SH
- Terminal Dependencies
- X.PP
- While the newer version of
- X.I wm
- uses
- X.I curses
- to perform all terminal-dependent operations in a
- terminal-independent fashion, terminal dependencies can be
- isolated fairly easily even without
- X.I curses .
- All terminal-dependent code in the original
- X.I wm
- is restricted to a collection of five simple procedures.
- They were originally written separately for each type of terminal,
- but have also been written in terms of the terminal-independent interface,
- X.I termcap ,
- for systems that have it.
- X.PP
- The five procedures perform the following tasks:
- X.RS
- X.IP \fBttyinit\fP 15
- Performs any necessary initialization for the terminal.
- X.IP \fBttyclose\fP 15
- Performs any necessary closing for the terminal before
- X.I wm
- exits or suspends.
- X.IP \fBttymov\fP 15
- Moves the terminal cursor to a given row and column.
- X.IP \fBclearscreen\fP 15
- Clears the terminal screen.
- X.IP \fBclearline\fP 15
- Clears from the cursor to end of the current line
- (not mandatory).
- X.RE
- X.LP
- XFor each of several common terminals, the definitions of these
- procedures comprise about 15 lines of code altogether.
- X.PP
- This approach isolates terminal dependencies sufficiently that
- X.I wm
- can also be adapted for use on graphic displays
- by replacing the above procedures and making other minor changes.
- XSuch a version of
- X.I wm
- has been written to produce output suitable
- for the standard UNIX plot filters (plus some added commands for
- raster graphic displays) and used with a Genisco frame buffer.
- Windows may be in various colors and may use different fonts for their text.
- X.SH
- Design for Version 4.2 UNIX
- X.PP
- Berkeley Version 4.2 VAX UNIX provides new features that make it
- possible to improve
- X.I wm
- significantly.
- By using pseudo-terminals instead of pipes for interprocess
- communication, several of the problems discussed above disappear.
- In addition, the synchronous input/output multiplexing feature of
- the new UNIX makes the former division of
- X.I wm
- into processes as dictated by the blocking read unnecessary.
- A revised version of
- X.I wm ,
- then, solves many of the earlier problems and runs in a single
- process (plus the user's shells).
- It is, however, less interesting and certainly less portable than
- the initial version.
- Again, the facilities are provided entirely in user-level processes,
- without the need for kernel modifications.
- X.PP
- This version of
- X.I wm
- reads from the keyboard and also from the pseudo-terminals associated
- with each window, in a round-robin, using the multiplexed read call
- X.I (select) .
- Keyboard input consisting of text is sent to the pseudo-terminal
- associated with the current window.
- The pseudo-terminal driver itself handles
- echoing (when enabled) and intraline editing,
- obviating the need for
- X.I wm
- to duplicate these functions.
- Keyboard input consisting of
- X.I wm
- commands is processed directly;
- text input is sent to the appropriate pseudo-terminal.
- Output from the pseudo-terminals is read by
- X.I wm ,
- interpreted in terms of
- the cursor control commands of a simple virtual terminal defined by
- X.I wm ,
- and then added to the appropriate screen window for processing by the
- X.I curses
- package\*(<.\*([.1\*(.]\*(>.
- X.PP
- This version of
- X.I wm
- comprises about 1000 lines of C code, all in a single process.
- XFigure 3 shows the architecture of the program.
- X.SH
- Remarks and Problems with Version 4.2 UNIX
- X.PP
- XSince each window is implemented with a pseudo-terminal, the fact
- that a program is running in a window rather than on a real
- terminal is transparent to most programs.
- XSpecifically,
- most screen editors and games may be used, and
- X.I stty
- may be called to change characteristics such as echoing or line editing
- individually for each window.
- XFor example, note that one of the windows in Figure 1 is running
- X.I vi ,
- which has adjusted itself to the window size.
- XSome programs, however, assume that their output devices are
- of some minimum size;
- they will not run well in very small windows.
- Also, programs that attempt to manipulate the controlling
- terminals of process groups will not work properly under
- X.I wm .
- XFor this reason,
- X.I csh
- cannot currently be run in the individual windows instead of
- X.I sh .
- X.PP
- It is generally
- not possible to move a window while an interactive
- program (other than a shell) is running in it.
- XFirst, this is necessary because, whenever a window is moved,
- X.I wm
- sends a shell command to change the
- X.I TERMCAP
- variable for the shell in that window, to describe its new size.
- A more fundamental reason is that the
- X.I curses
- library routines (sensibly)
- do not expect the terminal description to change while
- a program is running, and so make no provision for checking for or
- adapting to such changes.
- X.PP
- XSince pseudo-terminals are a system-wide resource and are usually fixed in
- number, the total number of
- windows that can be in use by all users at any one time
- is limited to the number of pseudo-terminals made available to
- X.I wm .
- X.PP
- A facility for communicating between windows is now easy to provide.
- XSince each window uses a pseudo-terminal, any data sent to its
- slave pseudo-terminal
- will appear in the window;
- and pseudo-terminals are in the name space of the UNIX file
- system and thus available to other processes.
- To simplify use of this feature, when a window is created and a
- pseudo-terminal obtained for it,
- a link to the name of its slave pseudo-terminal is created
- in the user's current directory.
- Any program inside or outside
- X.I wm
- can then write to or read from that file name without prearrangement.
- X.SH
- Program Versions
- X.PP
- These programs are written in C for use with UNIX.
- There are three principal versions:
- X.B wm.v6 ,
- X.B wm.v7 ,
- and
- X.B wm.v42 .
- The first, as described above,
- runs under unmodified Version 6 UNIX on a PDP-11.
- The code for this version was frozen and abandoned several years
- ago, but it is still available.
- X.B Wm.v7
- runs under Version 7 UNIX,
- and the same code also runs on Berkeley 2.8
- and also on a VAX on Berkeley 4.1 and 4.2.
- No changes in the source code are required between the PDP-11
- and VAX, except that constants for the maximum number and size of windows
- are limited by the available memory on a PDP-11.
- This version
- is similar in design to
- X.B wm.v6 ,
- which was described above, but has a number of improvements.
- The newest version,
- X.B wm.v42 ,
- runs only under Berkeley 4.2 on a VAX,
- as described in this paper.
- It uses the
- X.I select
- synchronous input/output multiplexing call,
- which is unique to 4.2, and also other features
- that are found in some, but not all, versions of UNIX, such as
- pseudo-terminals and
- X.I curses .
- At this writing, this version is not yet thoroughly tested on 4.2.
- An intermediate version for use with Versions 2.8 or 4.1
- can also be constructed by adapting some of the features of
- X.B wm.v42
- to
- X.B wm.v7 .
- XFor example, the use of
- X.I curses
- can certainly be adapted to 2.8;
- pseudo-terminals are available on some versions of 4.1;
- and some versions of 4.1 can also simulate a non-blocking read
- on a pseudo-terminal or a short time-out.
- X.SH
- Availability
- X.PP
- Three versions of
- X.I wm
- are available to interested researchers.
- X.RS
- X.IP "\fBwm.v6\fP" 10
- XFor Version 6 UNIX.
- X.IP "\fBwm.v7\fP" 10
- XFor Version 7 UNIX, also runs on Berkeley 2.8, 4.1, and 4.2.
- X.IP "\fBwm.v42\fP" 10
- XFor Berkeley 4.2 UNIX only (but has some features than can be retrofitted to
- X.B wm.v7 ).
- X.RE
- X.LP
- The code can be obtained over the Arpanet by sending a request to
- X.\" the two (hy is to prevent the hyphenation algorithm from splitting nrl-css
- jacob@nrl\(hycss.
- The author can also be reached via uucp
- at ...!decvax!linus!nrl\(hycss!jacob.
- X.SH
- Conclusions
- X.PP
- It is demonstrably feasible to provide a useful and efficient
- display window management facility in UNIX at the user level,
- without support from kernel modifications.
- XSuch a facility can even be provided for the original Version 6 UNIX,
- although some improvements are obtainable by exploiting features
- provided by more recent versions of UNIX.
- X.SH
- Acknowledgments
- X.PP
- I would like to thank
- Mark Cornwell, Rudy Krutar, Alan Parker, and Mark Weiser
- for helpful discussions of this work.
- X.]<
- X.\"Arnold.K.-1980-1
- X.ds [F 1
- X.]-
- X.ds [A K. Arnold
- X.ds [T Screen Updating and Cursor Movement Optimization
- X.ds [R University of California, Berkeley
- X.ds [D 1980
- X.nr [T 0
- X.nr [A 0
- X.nr [O 0
- X.][ 4 tech-report
- X.\"Bolt.R.-1979-2
- X.ds [F 2
- X.]-
- X.ds [A R. Bolt
- X.ds [T Spatial Data Management
- X.ds [I Architecture Machine Group, Massachusetts Institute of Technology
- X.ds [R Technical Report
- X.ds [D 1979
- X.nr [T 0
- X.nr [A 0
- X.nr [O 0
- X.][ 4 tech-report
- X.\"Herot.C.F.-1980-3
- X.ds [F 3
- X.]-
- X.ds [A C.F. Herot
- X.as [A ", R. Carling
- X.as [A ", M. Friedell
- X.as [A ", and D. Kramlich
- X.ds [T A Prototype Spatial Data Management System
- X.ds [J Computer Graphics
- X.ds [V 14
- X.ds [N 3
- X.ds [P 63-70
- X.nr [P 1
- X.ds [D 1980
- X.nr [T 0
- X.nr [A 0
- X.nr [O 0
- X.][ 1 journal-article
- X.\"Horton.M.-1982-4
- X.ds [F 4
- X.]-
- X.ds [A M. Horton
- X.ds [I personal communication
- X.ds [D September 8, 1982
- X.nr [T 0
- X.nr [A 0
- X.nr [O 0
- X.][ 2 book
- X.\"Joy.W.-1980-5
- X.ds [F 5
- X.]-
- X.ds [A W. Joy
- X.ds [T An Introduction to the C Shell
- X.ds [R University of California, Berkeley
- X.ds [D November 1980
- X.nr [T 0
- X.nr [A 0
- X.nr [O 0
- X.][ 4 tech-report
- X.\"Murrel.S.-1983-6
- X.ds [F 6
- X.]-
- X.ds [A S. Murrel
- X.ds [T Computer Communication System Design Affects Group Decision Making
- X.ds [J Proc. Human Factors in Computer Systems Conference
- X.ds [D 1983
- X.ds [P 63-67
- X.nr [P 1
- X.nr [T 0
- X.nr [A 0
- X.nr [O 0
- X.][ 1 journal-article
- X.\"Pike.R.-1983-7
- X.ds [F 7
- X.]-
- X.ds [A R. Pike
- X.ds [T Graphics in Overlapping Bitmap Layers
- X.ds [J ACM Transactions on Graphics
- X.ds [V 2
- X.ds [N 2
- X.ds [D 1983
- X.nr [T 0
- X.nr [A 0
- X.nr [O 0
- X.][ 1 journal-article
- X.\"Teitelman.W.-1979-8
- X.ds [F 8
- X.]-
- X.ds [A W. Teitelman
- X.ds [T A Display Oriented Programmer's Assistant
- X.ds [J International Journal of Man-Machine Studies
- X.ds [V 11
- X.ds [P 157-187
- X.nr [P 1
- X.ds [D 1979
- X.nr [T 0
- X.nr [A 0
- X.nr [O 0
- X.][ 1 journal-article
- X.\"Weiser.M.-1983-9
- X.ds [F 9
- X.]-
- X.ds [A M. Weiser
- X.as [A ", C. Torek
- X.as [A ", R. Trigg
- X.as [A ", and R. Wood
- X.ds [T The Maryland Window System
- X.ds [R Technical Report 1271
- X.ds [I Computer Science Department, University of Maryland
- X.ds [D 1983
- X.nr [T 0
- X.nr [A 0
- X.nr [O 0
- X.][ 4 tech-report
- X.]>
- SHAR_EOF
- if test 22963 -ne "`wc -c < 'Paper.jacob'`"
- then
- echo shar: error transmitting "'Paper.jacob'" '(should have been 22963 characters)'
- fi
- fi # end of overwriting check
- # End of shell archive
- exit 0
-